/*
 * @Author: xiaosihan 
 * @Date: 2023-02-06 15:22:57 
 * @Last Modified by: xiaosihan
 * @Last Modified time: 2024-04-29 08:58:46
 */
import { autorun } from "mobx";
import { Fog, Vector3 } from "three";
import ThreeBase from "three-base";
import Transition from "three-base/Transition";
import Btns from "./Btns";
import EatrhMesh from "./EatrhMesh";
import HtmlSprite from "./HtmlSprite";
import Mark from "./Mark";
import { Beijing, Hamburg, Madrid, USA } from "./config";
import earthStore from "./earthStore";
import { MarkParam } from "./type";

/**
 * @class HomeRender
 * @extends {ThreeBase}
 */
class Earth extends ThreeBase {

    constructor() {
        super();
    }

    //文本弹窗
    htmlSprite = new HtmlSprite();

    // 切换按钮
    btns = new Btns([Hamburg, Madrid, USA, Beijing]);

    //设置容器
    async setContainer(div: HTMLDivElement | null) {
        if (div) {
            div.style.position = (div.style.position || "relative");
            super.setContainer(div);
            div.appendChild(this.htmlSprite.root);
            div.appendChild(this.btns.root);
        }
    }

    init() {
        super.init();
        this.scene.fog = new Fog("#44757e", 2.3, 3.5);

        this.axesHelper.visible = false;
        this.gridHelper.visible = false;
        this.controls.enableZoom = false;
        this.controls.enablePan = false;
        this.controls.autoRotate = true;
        this.controls.autoRotateSpeed = -1;
        this.controls.rotateSpeed = 1;

        // this.controls.maxPolarAngle = (Math.PI / 4);
        // this.controls.minPolarAngle = (Math.PI / 4);

        this.resetLookAt({
            center: new Vector3(0, 0, 0),
            position: new Vector3(0.571, 1.829, 1.757)
        });
    }

    // 控制自动旋转
    dispose = autorun(() => {
        const { autoRotation, active } = earthStore;
        this.controls.autoRotate = (autoRotation && !active);
    });

    transtion = (() => {
        let init = true;
        const { position } = this.getLookAt();
        const transtion = new Transition({ y: position.y });
        transtion.setBezier([0.8, 0, 0.62, 1]);
        transtion.onChange(({ y }) => {
            if (!init) {
                init = false;
                const polarAngle = Math.acos(y / 2.6);
                this.controls.minPolarAngle = polarAngle;
                this.controls.maxPolarAngle = polarAngle;
            }
        })
        return transtion;
    })();


    // 选中状态控制视角
    dispose2 = autorun(async () => {
        const { active } = earthStore;
        if (active) {
            let markParam = {
                position: new Vector3(0, 0, 3),
                title: "",
                content: ""
            }
            //旋转到目标位置
            switch (active) {
                case USA.title:
                    markParam = USA;
                    break;
                case Hamburg.title:
                    markParam = Hamburg;
                    break;
                case Madrid.title:
                    markParam = Madrid;
                    break;
                case Beijing.title:
                    markParam = Beijing;
                    break;
                default:
                    break;
            }

            // this.controls.minPolarAngle = 0;
            // this.controls.maxPolarAngle = Math.PI;

            this.htmlSprite.setTitle(markParam.title);
            this.htmlSprite.setContent(markParam.content);
            const { position } = this.getLookAt()
            await Promise.all([
                this.transtion
                    .reset({
                        y: position.y
                    })
                    .set({
                        y: markParam.position.clone().setLength(2.6).y
                    }),
                this.setLookAt({
                    center: new Vector3(0, 0, 0),
                    position: markParam.position.clone().setLength(2.6),
                })
            ]);

            this.controls.minPolarAngle = 0;
            this.controls.maxPolarAngle = Math.PI;

            if (earthStore.active) {
                this.htmlSprite.setShow(true);
            }

        } else {
            this.htmlSprite.setShow(false);
            const { position, center } = this.getLookAt();
            const { y } = position;
            const currentY = 2.6 * Math.cos(Math.PI / 4);
            do {
                position.setY(currentY);
                position.setLength(2.6);
            } while (Math.abs(position.y - currentY) > 0.001);

            await Promise.all([
                this.transtion
                    .reset({
                        y: y
                    })
                    .set({
                        y: position.y
                    }),
                this.setLookAt({
                    center: new Vector3(0, 0, 0),
                    position: position
                })
            ]);

            earthRender.controls.minPolarAngle = 0;
            earthRender.controls.maxPolarAngle = Math.PI;
        }
    });

    //地球模型
    eatrhMesh = (() => {
        const eatrhMesh = new EatrhMesh();
        this.scene.add(eatrhMesh);
        return eatrhMesh;
    })();

    // 创建地球点标记
    creatMark(markParam: MarkParam) {
        const mark = new Mark(markParam.title);
        mark.position.copy(markParam.position).multiplyScalar(1.01);
        mark.lookAt(this.scene.position);
        mark.addEventListener("click", e => {
            earthStore.setActive(markParam.title);
        });
        mark.addEventListener("mouseenter", e => {
            earthStore.setAutoRotation(false);
        });
        mark.addEventListener("mouseleave", e => {
            earthStore.setAutoRotation(true);
        });
        mark.onAfterRender = () => {
            // 如果选中的是这个标记点就更具这个标记点计算位置弹窗的位置
            if (earthStore.active === markParam.title) {
                const worldPosition = mark.getWorldPosition(new Vector3());
                const p = this.v3tov2(worldPosition);
                this.htmlSprite.setPosition(p.x, p.y);
                this.htmlSprite.setShow(mark.spriteTextOnFront);
            }
        }
        this.scene.add(mark);
        return mark;
    }

    //标记点1 德国汉堡 Hamburg, Germany
    mark1 = this.creatMark(Hamburg);

    //标记点2 西班牙马德里  Madrid, Spain
    mark2 = this.creatMark(Madrid);

    // 美国德州 Texas, USA
    mark3 = this.creatMark(USA);

    // 中国北京 Beijing, China
    mark4 = this.creatMark(Beijing);

    render(): void {
        this.getCamera().position.setLength(2.6);
        super.render();
    }

}


const earthRender = window.earthRender = new Earth();

export default earthRender;